package com.scr1pt.extension

import com.scr1pt.extension.model.date.DateRange
import com.scr1pt.extension.model.date.TimeSpan
import java.text.SimpleDateFormat
import java.util.*

/**
 * 说明: 时间类扩展
 *
 * 创建者: tum0r
 *
 * 时间: 2021/8/18 20:08
 */

/**
 * 获取时间的日期部分
 */
fun Date.dateTime(): Date {
    val calendar = Calendar.getInstance()
    calendar.timeInMillis = 0
    calendar.set(this.getTimeYears(), this.getTimeMonths() - 1, this.getTimeDays(), 0, 0, 0)
    return calendar.time
}

/**
 * 获取日期的某一部分
 *
 * @param[mode] 代表某一部分的值
 */
private fun Date.getValue(mode: Int): Int {
    val calendar = Calendar.getInstance()
    calendar.time = this
    return calendar.get(mode)
}

/**
 * 获取日期的年
 */
fun Date.getTimeYears(): Int = getValue(Calendar.YEAR)

/**
 * 获取日期的月，从1开始
 */
fun Date.getTimeMonths(): Int = getValue(Calendar.MONTH) + 1

/**
 * 获取日期的天
 */
fun Date.getTimeDays(): Int = getValue(Calendar.DATE)

/**
 * 获取时间的时
 */
fun Date.getTimeHours(): Int = getValue(Calendar.HOUR)

/**
 * 获取时间的分
 */
fun Date.getTimeMinutes(): Int = getValue(Calendar.MINUTE)

/**
 * 获取时间的秒
 */
fun Date.getTimeSeconds(): Int = getValue(Calendar.SECOND)

/**
 * 获取时间的毫秒
 */
fun Date.getTimeMillionSeconds(): Int = getValue(Calendar.MILLISECOND)

/**
 * 增加/减少时间的某一部分值
 *
 * @param[amount] 增加/减少的数量
 * @param[mode] 代表某一部分的值
 */
private fun Date.add(amount: Int, mode: Int): Date {
    val calendar = Calendar.getInstance()
    calendar.time = this
    calendar.add(mode, amount)
    return calendar.time
}

/**
 * 增加/减少amount年
 *
 * @param[amount] 增加/减少的数量
 */
fun Date.addYears(amount: Int): Date = add(amount, Calendar.YEAR)

/**
 * 增加/减少amount月
 *
 * @param[amount] 增加/减少的数量
 */
fun Date.addMonths(amount: Int): Date = add(amount, Calendar.MONTH)

/**
 * 增加/减少amount日
 *
 * @param[amount] 增加/减少的数量
 */
fun Date.addDays(amount: Int): Date = add(amount, Calendar.DATE)

/**
 * 增加/减少amount小时
 *
 * @param[amount] 增加/减少的数量
 */
fun Date.addHours(amount: Int): Date = add(amount, Calendar.HOUR)

/**
 * 增加/减少amount分
 *
 * @param[amount] 增加/减少的数量
 */
fun Date.addMinutes(amount: Int): Date = add(amount, Calendar.MINUTE)

/**
 * 增加/减少amount秒
 *
 * @param[amount] 增加/减少的数量
 */
fun Date.addSeconds(amount: Int): Date = add(amount, Calendar.SECOND)

/**
 * 增加/减少amount毫秒
 *
 * @param[amount] 增加/减少的数量
 */
fun Date.addMillionSeconds(amount: Int): Date = add(amount, Calendar.MILLISECOND)

/**
 * 格式化时间
 *
 * @param[format] 格式化的格式
 */
@JvmOverloads
fun Date.format(format: String = "yyyy-MM-dd HH:mm:ss"): String = SimpleDateFormat(format).format(this)

/**
 * 获取开始时间
 */
fun Date.startTime(): Long = this.time

/**
 * 获取结束时间
 */
fun Date.endTime(): Long = if (this.time != 0L) addDays(1).time else Date().time

/**
 * 两个时间类型相减的差值，精度为毫秒
 *
 * @param[date] 与目标日期之间的差值
 */
operator fun Date.minus(date: Date): TimeSpan = TimeSpan(this.time - date.time)

/**
 * 根据年月日等信息获取日期
 *
 * @param[year] 年
 * @param[month] 月，从1开始
 * @param[day] 日
 * @param[hour] 时
 * @param[minute] 分
 * @param[second] 秒
 * @param[millisecond] 毫秒
 */
@JvmOverloads
fun getDate(year: Int = 1970, month: Int = 1, day: Int = 1, hour: Int = 0, minute: Int = 0, second: Int = 0, millisecond: Int = 0): Date {
    val calendar = Calendar.getInstance()
    calendar.timeInMillis = millisecond.toLong()
    calendar.set(year, month - 1, day, hour, minute, second)
    return calendar.time
}

/**
 * 从当前日期到目标日期的每天日期，闭区间
 *
 * @param[target] 目标日期
 */
infix operator fun Date.rangeTo(target: Date): DateRange = DateRange(this, target, 1)

/**
 * 从当前日期到目标日期的每天倒数日期，闭区间
 *
 * @param[target] 目标日期
 */
infix fun Date.downTo(target: Date): DateRange = DateRange(this, target, -1)

/**
 * 从当前日期到目标日期的每天日期，左开右闭区间
 *
 * @param[target] 目标日期
 */
infix fun Date.until(target: Date): DateRange = DateRange(this, target.addDays(-1), 1)

/**
 * 从当前日期到目标日期的每天倒数日期，左开右闭区间
 *
 * @param[target] 目标日期
 */
infix fun Date.downToUntil(target: Date): DateRange = DateRange(this, target.addDays(1), -1)